package com.ea.config;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;


import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;



import com.ea.common.Constants.UserConstants;
import com.ea.common.filter.LogoutFilter;
import com.ea.common.filter.RestfulFilter;
import com.ea.common.shiro.SessionManager;






/**
 * shiro配置
 * 
 * @author 邢广军
 *
 */

@Configuration
public class ShiroConfig {
	

	
	//session 失效时间（默认为30分钟 单位：毫秒）
	private long sessionTimeout=1000*60*30;
	//session 验证失效时间（默认为15分钟 单位：毫秒）
	private long sessionValidationInterval=1000*60*15;
	
	
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		//1.创建ShiroFilterFactoryBean
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

		shiroFilterFactoryBean.setSecurityManager(securityManager);

		// 拦截器. 过虑器链定义，从上向下顺序执行，一般将/**放在最下边
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		//对静态资源设置匿名访问  配置为anon为匿名访问
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/fonts/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/modular/**", "anon");
		filterChainDefinitionMap.put("/files/*", "anon");
		//session过期地址
		filterChainDefinitionMap.put("/sessionout", "anon");
		//登录地址
		filterChainDefinitionMap.put("/login", "anon");
		//验证码地址
		filterChainDefinitionMap.put("/kaptcha", "anon");
	    // 请求 logout.action地址，shiro去清除session
		filterChainDefinitionMap.put("/logout", "logout");
		
		// /** = authc 所有url都必须认证通过才可以访问
		filterChainDefinitionMap.put("/**", "authc");

		// loginUrl认证提交地址，如果没有认证将会请求此地址进行认证，请求此地址将由formAuthenticationFilter进行表单认证 
		shiroFilterFactoryBean.setLoginUrl("/login");
		//认证成功统一跳转到/index.html，建议不配置，shiro认证成功自动到上一个请求路径
		shiroFilterFactoryBean.setSuccessUrl("/index");
		//通过unauthorizedUrl指定没有权限操作时跳转页面
		//shiroFilterFactoryBean.setUnauthorizedUrl("/loginError");
		

		//退出拦截 退出成功后跳转/login.html
		LogoutFilter logoutFilter = new LogoutFilter();
		logoutFilter.setRedirectUrl("/login");

		//登录拦截器
		RestfulFilter restfulFilter = new RestfulFilter();
		

		//设置拦截器权限
		shiroFilterFactoryBean.getFilters().put("authc", restfulFilter);
		shiroFilterFactoryBean.getFilters().put("logout", logoutFilter);
		//shiroFilterFactoryBean中加入拦截器
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		
		return shiroFilterFactoryBean;
	}

	/**
	 *  securityManager安全管理器
	 * @param cacheManager
	 * @return
	 */
	@Bean
	public SecurityManager securityManager(EhCacheManager cacheManager) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		//设置认证拦截器
		securityManager.setRealm(myShiroRealm());
		securityManager.setCacheManager(cacheManager);
		securityManager.setSessionManager(getSessionManage());
		return securityManager;
	}

	
	
	/**
	 * 设置自定义认证拦截器
	 * @return
	 */
	@Bean
	public MyShiroRealm myShiroRealm() {
		MyShiroRealm myShiroRealm = new MyShiroRealm();
		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myShiroRealm;
	}

	/**
	 * 凭证匹配器
	 * 指定加密算法及加密次数
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(UserConstants.HASH_ITERATIONS);

		return hashedCredentialsMatcher;
	}

	/**
	 * Shiro生命周期处理器
	 * 
	 * @return
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	/**
	 * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),
	 * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
	 * 
	 * @return
	 */
	@Bean
	@DependsOn({ "lifecycleBeanPostProcessor" })
	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		advisorAutoProxyCreator.setProxyTargetClass(true);
		return advisorAutoProxyCreator;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}
	
	
	
	
	
	
	@Bean(name = "sessionManager")
	public SessionManager getSessionManage() {
		SessionManager sessionManager = new SessionManager();
		//会话超时时间，单位：毫秒 
		sessionManager.setGlobalSessionTimeout(sessionTimeout);
		//定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话
		sessionManager.setSessionValidationInterval(sessionValidationInterval);
		sessionManager.setSessionValidationSchedulerEnabled(true);
		sessionManager.setSessionIdCookieEnabled(true);

		// -----可以添加session 创建、删除的监听器
		
		return sessionManager;
	}


	

}